/*
 * morsecodetalk - The Pidgin Plugin contains the entire Morse Code.
 * Have one more friend around to use it, it can be a lot of fun to 
 * communicate in this way.
 * Copyright (C) 2011 Beastieux Zeroo <the.beastieux@gmail.com>
 *

 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
 */

#include "internal.h"

#ifdef HAVE_CONFIG_H
#include <gdk/gdkkeysyms.h>
#include <config.h>
#endif

#ifndef PURPLE_PLUGINS
# define PURPLE_PLUGINS
#endif

#include "pluginpref.h"
#include "plugin.h"
#include "prefs.h"
#include "version.h"

#include "pidgin.h"

#include "gtkconv.h"
#include "gtkplugin.h"

#include "morse.h"
#include "morsecodetalk.h"

GtkWidget *window;

gboolean windows_id = FALSE;
gboolean decode_id = FALSE;
gboolean mouse_mode_id=FALSE;


int buffer_count;
int decode_mode_id=0;

unsigned int keys_entry_id;
unsigned int buff_entry_id;
unsigned int pressed_entry_id;
unsigned int release_entry_id;

gchar clic1_id[1024]=" ";


static void message_send_cb(GtkButton *button, PidginConversation *gtkconv)
{
	GtkTextBuffer *buf;
	GtkTextIter start, end;

	char resolv[1024]=" ";
	gchar *env=malloc(1024);

	buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->entry));

	gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER (buf), &start);
	gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buf), &end);

	buffer_count=gtk_text_buffer_get_char_count(buf);
	
	if(buffer_count<1024)
	{
		env=gtk_text_buffer_get_text(GTK_TEXT_BUFFER (buf),&start,&end,TRUE);
	}
	
	
	strcat(env," ");
	
	if( decode_id )	
	{	
		decode(env,resolv);
	}
	else
	{
		encode(env,resolv);	
	}

	if(buffer_count > 0)
		gtk_text_buffer_set_text(buf, resolv, -1);
	
	
}


gboolean txt_entrada_keypress(GtkWidget *widget,GdkEventKey *event,gpointer data)
{
  if ( decode_id )
  {
	  //raya y punto del teclado numeral
	  if ((event->keyval == GDK_KP_Subtract) || (event->keyval == GDK_KP_Decimal))
	  {
	    return FALSE;
	  }

	  //raya y punto del teclado textual
	  if ((event->keyval == GDK_minus) || (event->keyval == GDK_period))
	  {
	    return FALSE;
	  }
	  /* Permitimos borrar */
	  if ((event->keyval == GDK_BackSpace) || (event->keyval == GDK_Delete))
	  {
	    return FALSE;
	  }

	  //Permitimos algunas teclas especiales de desplazamiento… 
	  if ((event->keyval == GDK_Home) || (event->keyval == GDK_End) || (event->keyval == GDK_space))
	  {
	    return FALSE;
	  }
	
	  /* Permitimos barra */
	  //if ((event->keyval == GDK_KP_Divide) || (event->keyval == GDK_slash))
	  //{
	  // return FALSE;
	  //}

	  //tecla izquierda / derecha
	  if ((event->keyval == GDK_Left) || (event->keyval == GDK_Right))
	  {
	    return FALSE;
	  }

	  //tecla enter
	  if ((event->keyval == GDK_Return) || (event->keyval == GDK_KP_Enter))
	  {
			g_signal_emit_by_name(widget, "message_send");
	  }

	  return TRUE;
   }
   else
	return FALSE;
   
}

gint signal_handler_event(GtkWidget *widget, GdkEventButton *event, gpointer func_data)
{

	if ( decode_id && mouse_mode_id )
  	{
	  GtkTextBuffer *buf;
	  GtkTextIter iter;
	  GtkTextIter start, end;

	  buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget)); 
	
	  gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buf), &iter);
	  

	  gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER (buf), &start);
	  gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buf), &end);
	

	  if(event->button==1)
	  {
	   	if (gtk_text_buffer_get_has_selection(buf))
	  	{
			
			gtk_text_buffer_delete_selection(buf,FALSE,FALSE);
			  
	  	}
		else
		{	 

			  if(event->type==GDK_2BUTTON_PRESS)
			  {					

				gint i;
				gint tam=gtk_text_buffer_get_char_count(buf);
				gchar clic2_id[tam];
				gchar clic3_id[1024];
				

				memcpy(clic2_id,clic1_id,tam+1);				
				for(i=0;i<tam-2;i++)
				{
					clic3_id[i]=clic2_id[i];
				}

				strcat(clic3_id,"-");				
				gtk_text_buffer_set_text(buf,clic3_id, -1);
							
			  }
			  else if(event->type==GDK_BUTTON_PRESS)
			  {
				
				strcpy(clic1_id,gtk_text_buffer_get_text(GTK_TEXT_BUFFER (buf),&start,&end,TRUE));
				
				gtk_text_buffer_insert(buf,&iter,".", -1);
				
			  }
			  else if(event->type==GDK_3BUTTON_PRESS)
			  {
				return TRUE;
			  }
		}
	  }
	  else if(event->button==2)
	  {
		return TRUE;
	  }
	  else if(event->button==3) //right button
	  {
		if (gtk_text_buffer_get_has_selection(buf))
		{
			//gtk_text_buffer_delete(buf,&iter,&iter);
			gtk_text_buffer_place_cursor(buf,&iter);
		}
		else
		{
			gtk_text_buffer_insert(buf,&iter," ", -1);
			//buffer_count=gtk_text_buffer_get_char_count(buf);
		}
		return TRUE;
	  } 

	}
	
	return FALSE;
}


static void create_connections_pidgin(PidginConversation *gtkconv)
{
	//Conectar keys_entry_id
	keys_entry_id=gtk_signal_connect(GTK_OBJECT(gtkconv->entry),"key_press_event",
			   		 GTK_SIGNAL_FUNC(txt_entrada_keypress),NULL);
	
	//Conectar buff_entry_id
	buff_entry_id=g_signal_connect(G_OBJECT(gtkconv->entry), "message_send",
			 	       G_CALLBACK(message_send_cb), gtkconv);

	//Conectar pressed_entry_id : "button_release_event"/"button_press_event"
	pressed_entry_id=g_signal_connect(G_OBJECT(gtkconv->entry),"button_press_event",
                     		       G_CALLBACK(signal_handler_event),NULL);



}

static void remove_connections_pidgin(PidginConversation *gtkconv)
{

	//Desconectar keys_entry_id
	gtk_signal_disconnect(GTK_OBJECT(gtkconv->entry), keys_entry_id);

	//Desconectar buff_entry_id
	g_signal_handler_disconnect(G_OBJECT(gtkconv->entry), buff_entry_id);

	//Desconectar clic_entry_id
	g_signal_handler_disconnect(G_OBJECT(gtkconv->entry), pressed_entry_id);
	
}

static void conversation_displayed_cb(PidginConversation *gtkconv)
{
	create_connections_pidgin(gtkconv);
}


static void set_window_id_off()
{
	windows_id = FALSE;
}


static void set_window_id_on()
{
	windows_id = TRUE;
}


static void get_morsetable_frame()
{

	if( ! windows_id )
	{
	    

	    GtkWidget *label_up;
	    GtkWidget *label_right;
	    GtkWidget *label_left;
	    GtkWidget *box_up;
	    GtkWidget *box_down;
	    GtkWidget *separator;
	    
	    char str[1024];
	    int j;

	    set_window_id_on();
	 
	    /* create the main, top level, window */
	    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);


	    /* give it the title */
	    gtk_window_set_title (GTK_WINDOW (window), "Morse Code Chart");
	 
	    /* Connect the destroy signal of the window to gtk_main_quit
	     * When the window is about to be destroyed we get a notification and
	     * stop the main GTK+ loop
	     */
	   g_signal_connect (window, "destroy", G_CALLBACK (set_window_id_off), NULL);
	   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
 	   	
	   //In Label_up
	   label_up = gtk_label_new(NULL);
	   gtk_label_set_markup (GTK_LABEL(label_up), "<b>\nINTERNATIONAL MORSE CODE\n</b>");
	   //In Label_left
	   strcpy(str,"\n");
	   
	   for ( j = 0; j < (sizeof Code / sizeof *Code)/2; ++j )
	   {
	   	strcat(str,&Code[j].letter);
	   	strcat(str,"\t");
	   	strcat(str,Code[j].morse);
	   	strcat(str,"\n");
	   }
	   label_left = gtk_label_new(str);

	   //In Label_right
	   strcpy(str,"\n");
	   
	   for ( j = j; j < sizeof Code / sizeof *Code; ++j )
	   {
	   	strcat(str,&Code[j].letter);
	   	strcat(str,"\t");
	   	strcat(str,Code[j].morse);
	   	strcat(str,"\n");
	   }

	    label_right = gtk_label_new(str);

	    /* and insert it into the main window  */
	    box_down = gtk_hbox_new(FALSE, 0);
	    box_up = gtk_vbox_new(FALSE, 0);
	    separator=gtk_vseparator_new();
	    gtk_widget_set_size_request (separator, 5, 380);
	    
    	    gtk_box_pack_start(GTK_BOX(box_down), label_left, TRUE, TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(box_down), separator, FALSE, TRUE, 5);
	    gtk_box_pack_start(GTK_BOX(box_down), label_right, TRUE, TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(box_up), label_up, TRUE, TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(box_up), box_down, TRUE, TRUE, 0);

	    gtk_container_add (GTK_CONTAINER (window), box_up);

	    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
	    /* make sure that everything, window and label, are visible */
	    gtk_widget_show_all (window);
	 
	    /* start the main loop, and let it rest there until the application is closed */
	    gtk_main ();
   	} 
}

static void
mouse_mode_callback(const char *name, PurplePrefType type, gconstpointer val, gpointer null)
{
	mouse_mode_id=purple_prefs_get_bool(PREFS_BOOLEAN);
}

static void
decode_mode_callback(const char *name, PurplePrefType type, gconstpointer val, gpointer null)
{
	if (purple_prefs_get_int(PREFS_CHOICE) == 1)
	{	decode_id=FALSE;
		decode_mode_id=1;
	}else if (purple_prefs_get_int(PREFS_CHOICE) == 2){
		decode_id=TRUE;
		decode_mode_id=2;
	}
}

static PurplePluginPrefFrame * get_config_frame(PurplePlugin *plugin) {
	PurplePluginPrefFrame *frame;
	PurplePluginPref *ppref;
	
	purple_prefs_connect_callback(plugin, PREFS_BOOLEAN, mouse_mode_callback, NULL);
      	purple_prefs_connect_callback(plugin, PREFS_CHOICE, decode_mode_callback, NULL);

	frame = purple_plugin_pref_frame_new();

	ppref = purple_plugin_pref_new_with_label("Morse Code Inputs From Mouse:");
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(PREFS_BOOLEAN,"Enable/Disable");
	purple_prefs_set_bool(PREFS_BOOLEAN, mouse_mode_id);
	purple_plugin_pref_frame_add(frame, ppref);


	ppref = purple_plugin_pref_new_with_label("Select Mode:");
	purple_plugin_pref_frame_add(frame, ppref);
	
	ppref = purple_plugin_pref_new_with_name(PREFS_CHOICE);
	purple_plugin_pref_set_type(ppref, PURPLE_PLUGIN_PREF_CHOICE);
	purple_plugin_pref_add_choice(ppref, "From Text To Morse Code", GINT_TO_POINTER(1));
	purple_plugin_pref_add_choice(ppref, "From Morse Code To Text", GINT_TO_POINTER(2));
	purple_prefs_set_int(PREFS_CHOICE, decode_mode_id);
	purple_plugin_pref_frame_add(frame, ppref);

	
	ppref = purple_plugin_pref_new_with_label(_("[Features Not Yet Available]"));
	purple_plugin_pref_frame_add(frame, ppref);
	
	ppref = purple_plugin_pref_new_with_name_and_label(PREFS_INTEGER, "Volume:");
	purple_plugin_pref_set_bounds(ppref, 0, 0);
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(PREFS_INTEGER, "Pitch / Hz:");
	purple_plugin_pref_set_bounds(ppref, 0, 0);
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(PREFS_INTEGER, "Speed / wpm:");
	purple_plugin_pref_set_bounds(ppref, 0, 0);
	purple_plugin_pref_frame_add(frame, ppref);

	ppref = purple_plugin_pref_new_with_name_and_label(PREFS_INTEGER, "Farnsworth Speed / wpm:");
	purple_plugin_pref_set_bounds(ppref, 0, 0);
	purple_plugin_pref_frame_add(frame, ppref);
	

	

	return frame;
}

void plugin_action_help (PurplePluginAction *action) {
	
	purple_notify_message (NULL, PURPLE_NOTIFY_MSG_INFO, "Morse Code Talk",
	"Instructions: ","- Separate each Morse letter with one space.\n"
			 "- Separate each Morse word with three spaces.\n"
			 "- Example: HELP ME = .... . .-.. .--.   -- .\n"
			 "- One Click is a dot [.]\n"
			 "- Double Click is a line [-]\n"
			 "- Right Click is a Space [ ]\n"
			 "- In fact, you can also use the keyboard.",NULL, NULL);
}

void plugin_action_decodeOff (PurplePluginAction *action) {
	
	decode_id = FALSE;
	decode_mode_id=1;
	purple_notify_message (NULL, PURPLE_NOTIFY_MSG_INFO, "Morse Code Talk",
	"Enabled Mode: ","From Text To Morse Code", NULL, NULL);

}

void plugin_action_decodeOn (PurplePluginAction *action) {
	
	decode_id = TRUE;
	decode_mode_id=2;
	purple_notify_message (NULL, PURPLE_NOTIFY_MSG_INFO, "Morse Code Talk",
	"Enabled Mode: ","From Morse Code To Text", NULL, NULL);

}

GList * plugin_actions (PurplePlugin *plugin, gpointer context) {
	/* some C89 (a.k.a. ANSI C) compilers will warn if any variable declaration
	 * includes an initilization that calls a function.  To avoid that, we
	 * generally initialize our variables first with constant values like NULL
	 * or 0 and assign to them with function calls later */
	GList *list = NULL;

	list = g_list_append(list, purple_plugin_action_new("From Morse Code To Text", plugin_action_decodeOn));
	list = g_list_append(list, purple_plugin_action_new("From Text To Morse Code", plugin_action_decodeOff));
	list = g_list_append(list, purple_plugin_action_new("International Morse Code Chart", get_morsetable_frame));
	list = g_list_append(list, purple_plugin_action_new("Instructions", plugin_action_help));

	/* Once the list is complete, we send it to libpurple. */
	return list;
}


static PurplePluginUiInfo prefs_info = {
	get_config_frame,
	0,   /* page_num (Reserved) */
	NULL, /* frame (Reserved) */
	/* Padding */
	NULL,
	NULL,
	NULL,
	NULL
};

static gboolean plugin_load(PurplePlugin *plugin)
{
	GList *convs = purple_get_conversations();
	void *gtk_conv_handle = pidgin_conversations_get_handle();

	purple_signal_connect(gtk_conv_handle, "conversation-displayed", plugin,
	                      PURPLE_CALLBACK(conversation_displayed_cb), NULL);


	while (convs) {
		
		PurpleConversation *conv = (PurpleConversation *)convs->data;

		/* Setup Morse Code */
		if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) {
			create_connections_pidgin(PIDGIN_CONVERSATION(conv));
		}

		convs = convs->next;
	}


	return TRUE;
}

static gboolean plugin_unload(PurplePlugin *plugin)
{
	GList *convs = purple_get_conversations();

	while (convs) {
		PurpleConversation *conv = (PurpleConversation *)convs->data;

		/* Remove Morse Code */
		if (PIDGIN_IS_PIDGIN_CONVERSATION(conv)) {
			remove_connections_pidgin(PIDGIN_CONVERSATION(conv));
		}

		convs = convs->next;
	}
	
	gtk_widget_destroy(window);
	set_window_id_off();

	return TRUE;
}

static PurplePluginInfo info =
{
	PURPLE_PLUGIN_MAGIC,
	PURPLE_MAJOR_VERSION,                           /**< major version */
	PURPLE_MINOR_VERSION,                           /**< minor version */
	PURPLE_PLUGIN_STANDARD,                         /**< type */
	PIDGIN_PLUGIN_TYPE,                             /**< ui_requirement */
	0,                                              /**< flags */
	NULL,                                           /**< dependencies */
	PURPLE_PRIORITY_DEFAULT,                        /**< priority */
	PLUGIN_ID,                  			/**< id */
	PLUGIN_NAME,                  			/**< name */
	PLUGIN_VERSION,                               	/**< version */
	PLUGIN_SUMMARY,					/**< summary */
	PLUGIN_DESCRIPTION,				/**< description */
	PLUGIN_AUTHOR, 					/**< author */
	PLUGIN_HOME_URL,        			/**< homepage */
	plugin_load,                                    /**< load */
	plugin_unload,                                  /**< unload */
	NULL,                                           /**< destroy */
	NULL,                                           /**< ui_info */
	NULL,                                           /**< extra_info */
	&prefs_info,                           	        /**< prefs_info */
	plugin_actions,                                 /**< actions */
	/* padding */
	NULL,
	NULL,
	NULL,
	NULL
};

static void init_plugin(PurplePlugin *plugin)
{
	purple_prefs_add_none(PREFS_NAMESPACE);
	purple_prefs_add_bool(PREFS_BOOLEAN, FALSE);
	purple_prefs_add_int(PREFS_INTEGER, 0);
	purple_prefs_add_int(PREFS_CHOICE, 0);

}

PURPLE_INIT_PLUGIN(morsecodetalk, init_plugin, info)
